<template>
  <div class="pdfjs-viewer-root" ref="viewerRoot" :style="rootStyles">
    <!-- 顶部工具栏 -->
    <div class="pdfjs-toolbar" :style="toolbarStyles">
      <div class="pdfjs-toolbar-left">
        <button
          @click="toggleThumbnails"
          :title="showThumbnails ? '隐藏缩略图' : '显示缩略图'"
          :style="buttonStyles"
        >
          <svg width="18" height="18" viewBox="0 0 24 24">
            <path
              fill="currentColor"
              d="M4 5h16v2H4zm0 6h16v2H4zm0 6h16v2H4z"
            />
          </svg>
        </button>
        <span class="pdfjs-filename" :style="textStyles">{{ filename }}</span>
      </div>
      <div class="pdfjs-toolbar-center">
        <button @click="prevPage" :disabled="pageNumber <= 1" :style="buttonStyles">‹</button>
        <span :style="textStyles">{{ pageNumber }} / {{ numPages }}</span>
        <button @click="nextPage" :disabled="pageNumber >= numPages" :style="buttonStyles">›</button>
        <button @click="zoomOut" :style="buttonStyles">-</button>
        <span :style="textStyles">{{ (scale * 100).toFixed(0) }}%</span>
        <button @click="zoomIn" :style="buttonStyles">+</button>
      </div>
      <div class="pdfjs-toolbar-right">
        <button 
          v-if="showDownloadBtn"
          @click="downloadPdf" 
          title="下载"
          :style="buttonStyles"
        >
          <svg width="18" height="18" viewBox="0 0 24 24">
            <path
              fill="currentColor"
              d="M5 20h14v-2H5v2zm7-18v12.17l3.59-3.58L17 12l-5 5-5-5 1.41-1.41L11 14.17V2h2z"
            />
          </svg>
        </button>
        <button 
          v-if="showPrintBtn"
          @click="printPdf" 
          title="打印"
          :style="buttonStyles"
        >
          <svg width="18" height="18" viewBox="0 0 24 24">
            <path
              fill="currentColor"
              d="M19 8H5V5h14m0-2H5a2 2 0 0 0-2 2v5h18V5a2 2 0 0 0-2-2m1 7H4a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-7a2 2 0 0 0-2-2m-1 9H5v-5h14v5m-7-7a2 2 0 1 1 0-4 2 2 0 0 1 0 4z"
            />
          </svg>
        </button>
        <button 
          v-if="showFullscreenBtn"
          @click="toggleFullScreen" 
          title="全屏"
          :style="buttonStyles"
        >
          <svg width="18" height="18" viewBox="0 0 24 24">
            <path
              fill="currentColor"
              d="M7 14H5v5h5v-2H7v-3zm0-4V7h3V5H5v5h2zm10 7h-3v2h5v-5h-2v3zm0-12v3h2V5h-5v2h3z"
            />
          </svg>
        </button>
      </div>
    </div>
    <!-- 横向进度条，紧跟在工具栏下方 -->
    <div v-if="loading" class="pdf-indeterminate-bar">
      <div class="pdf-indeterminate-inner"></div>
    </div>
    
    <!-- 错误提示区域 -->
    <div v-if="errorState" class="pdfjs-error-container" :style="errorContainerStyles">
      <div class="pdfjs-error-content">
        <svg width="64" height="64" viewBox="0 0 24 24" class="error-icon">
          <path
            fill="currentColor"
            d="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-2 15l-5-5 1.41-1.41L10 14.17l7.59-7.59L19 8l-9 9z"
          />
        </svg>
        <h3 :style="errorTitleStyles">{{ errorTitle }}</h3>
        <p :style="errorMessageStyles">{{ errorMessage }}</p>
        <button 
          v-if="showRetryBtn && props.src"
          @click="retryLoad"
          class="retry-btn"
          :style="retryButtonStyles"
        >
          重新加载
        </button>
      </div>
    </div>

    <div v-else class="pdfjs-main">
      <!-- 左侧缩略图 -->
      <div
        class="pdfjs-thumbnails"
        v-show="showThumbnails"
        ref="thumbnailsContainer"
        :style="thumbnailsStyles"
      >
        <div
          v-for="page in numPages"
          :key="page"
          class="pdfjs-thumbnail"
          :style="thumbnailsItemStyles"
          :class="{ active: pageNumber === page }"
          @click="goToPage(page)"
          :ref="
            (el) => {
              thumbRefs[page - 1] = el;
            }
          "

        >
          <canvas :ref="(el) => (thumbnailCanvases[page - 1] = el)"></canvas>
          <span :style="thumbnailTextStyles">{{ page }}</span>
        </div>
      </div>
      <!-- 右侧主内容 -->
      <div class="pdfjs-content" ref="contentRef" :style="contentStyles">
        <div
          v-for="page in numPages"
          :key="page"
          class="pdfjs-page"
          :ref="
            (el) => {
              pageRefs[page - 1] = el;
            }
          "
        >
          <PdfViewer
            v-if="visiblePages.has(page)"
            :src="src"
            :page="page"
            :scale="scale"
            @rendered="onPageRendered(page)"
          />
          <div
            v-else
            class="pdfjs-page-placeholder"
            :style="{
              width: pageWidths[page - 1]
                ? pageWidths[page - 1] + 'px'
                : '800px',
              height: pageHeights[page - 1]
                ? pageHeights[page - 1] + 'px'
                : '1000px',
              backgroundColor: contentBackgroundColor,
            }"
          ></div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import {
  ref,
  reactive,
  watch,
  computed,
  nextTick,
  onMounted,
  onBeforeUnmount,
} from "vue";
import { getDocument, GlobalWorkerOptions } from "pdfjs-dist";
import PdfViewer from "./PdfViewer.vue";

/**
 * 配置PDF.js Worker
 * 直接使用CDN方式确保最佳兼容性
 * @author Ning,Li
 */
const configurePdfWorker = () => {
  // 直接使用CDN确保兼容性
  GlobalWorkerOptions.workerSrc = `https://unpkg.com/pdfjs-dist@3.11.174/build/pdf.worker.min.js`;
};

// 初始化PDF.js Worker
configurePdfWorker();

/**
 * PDF查看器组件属性定义
 * @author Ning,Li
 */
const props = defineProps({
  /** PDF文件路径 */
  src: {
    type: String,
    default: ''
  },
  /** 是否显示下载按钮 */
  showDownloadBtn: {
    type: Boolean,
    default: true
  },
  /** 是否显示打印按钮 */
  showPrintBtn: {
    type: Boolean,
    default: true
  },
  /** 是否显示全屏按钮 */
  showFullscreenBtn: {
    type: Boolean,
    default: true
  },
  /** 是否显示重试按钮 */
  showRetryBtn: {
    type: Boolean,
    default: true
  },
  /** 工具栏背景色 */
  toolbarBackgroundColor: {
    type: String,
    default: '#333'
  },
  /** 工具栏文字颜色 */
  toolbarTextColor: {
    type: String,
    default: '#fff'
  },
  /** 内容区域背景色 */
  contentBackgroundColor: {
    type: String,
    default: '#222'
  },
  /** 缩略图区域背景色 */
  thumbnailBackgroundColor: {
    type: String,
    default: '#232323'
  },
  thumbnailItemBackgroundColor: {
    type: String,
    default: '#232323'
  },
  /** 主题色（用于按钮悬停、激活状态等） */
  primaryColor: {
    type: String,
    default: '#42b983'
  },
  /** 按钮悬停背景色 */
  buttonHoverColor: {
    type: String,
    default: '#444'
  }
});

// 计算样式
const rootStyles = computed(() => ({
  backgroundColor: props.contentBackgroundColor,
  '--button-hover-color': props.buttonHoverColor,
  '--primary-color': props.primaryColor
}));

const toolbarStyles = computed(() => ({
  backgroundColor: props.toolbarBackgroundColor,
  color: props.toolbarTextColor
}));

const buttonStyles = computed(() => ({
  color: props.toolbarTextColor,
  transition: 'background 0.2s'
}));

const textStyles = computed(() => ({
  color: props.toolbarTextColor
}));

const thumbnailsStyles = computed(() => ({
  backgroundColor: props.thumbnailBackgroundColor
}));

const thumbnailsItemStyles = computed(() => ({
  backgroundColor: props.thumbnailItemBackgroundColor
}));

const thumbnailItemStyles = () => ({});

const thumbnailTextStyles = computed(() => ({
  color: '#bbb'
}));

const contentStyles = computed(() => ({
  backgroundColor: props.contentBackgroundColor
}));

const errorContainerStyles = computed(() => ({
  backgroundColor: props.contentBackgroundColor,
  color: props.toolbarTextColor
}));

const errorTitleStyles = computed(() => ({
  color: props.toolbarTextColor
}));

const errorMessageStyles = computed(() => ({
  color: '#bbb'
}));

const retryButtonStyles = computed(() => ({
  backgroundColor: props.primaryColor,
  color: '#fff'
}));

// 错误状态管理
const errorState = ref(false);
const errorTitle = ref('');
const errorMessage = ref('');

// 现有的响应式变量
const observedThumbs = ref({});
const renderedThumbs = ref({});
const filename = computed(() => {
  if (!props.src) return 'PDF文档';
  return props.src.split("/").pop() || "PDF文档";
});
const pendingThumbs = ref(new Set());
const pendingPages = ref(new Set());
const loading = ref(false);
const thumbnailCanvases = ref([]);
const numPages = ref(0);
const pageNumber = ref(1);
const scale = ref(1.0);
let pdfDoc = null;
const showThumbnails = ref(true);
const thumbRefs = ref([]);
const thumbnailsContainer = ref(null);
const viewerRoot = ref(null);
const contentRef = ref(null);
const pageRefs = ref([]);

const visiblePages = ref(new Set());
const PAGE_WINDOW = 5;
const pageWidths = ref([]);
const pageHeights = ref([]);

/**
 * 重试加载PDF
 * @author Ning,Li
 */
const retryLoad = () => {
  errorState.value = false;
  loadPdf();
};

/**
 * 设置错误状态
 * @author Ning,Li
 * @param {string} title - 错误标题
 * @param {string} message - 错误消息
 */
const setErrorState = (title, message) => {
  errorState.value = true;
  errorTitle.value = title;
  errorMessage.value = message;
  loading.value = false;
  numPages.value = 0;
  pageNumber.value = 1;
};

const loadPdf = async () => {
  // 检查src是否为空或无效
  if (!props.src || props.src.trim() === '') {
    setErrorState('未指定PDF文件', '请提供有效的PDF文件路径');
    return;
  }

  // 重置状态
  errorState.value = false;
  loading.value = true;
  pageNumber.value = 1;
  numPages.value = 0;
  visiblePages.value = new Set();
  pageWidths.value = [];
  pageHeights.value = [];
  renderedThumbs.value = {};
  observedThumbs.value = {};
  pendingThumbs.value.clear();
  pendingPages.value.clear();
  
  // 清空缩略图
  thumbnailCanvases.value.forEach(canvas => {
    if (canvas) {
      canvas.width = 0;
      canvas.height = 0;
      canvas.removeAttribute('data-rendered');
      canvas.removeAttribute('data-verified');
    }
  });
  thumbnailCanvases.value = [];
  
  // 销毁旧文档
  if (pdfDoc && pdfDoc.destroy) {
    await pdfDoc.destroy();
    pdfDoc = null;
  }
  
  try {
    // 开始加载PDF文档
    const loadingTask = getDocument(props.src);
    
    // 在PDF加载过程中，尝试从缓存恢复第一页缩略图
    nextTick(() => {
      if (thumbnailCanvases.value[0]) {
        try {
          const cachedThumb = localStorage.getItem(`pdf_thumb_cache_${props.src}_1`);
          if (cachedThumb) {
            const canvas = thumbnailCanvases.value[0];
            const img = new Image();
            img.onload = () => {
              // 设置一个临时尺寸
              canvas.width = img.width;
              canvas.height = img.height;
              canvas.style.width = `${img.width / (window.devicePixelRatio || 1)}px`;
              canvas.style.height = `${img.height / (window.devicePixelRatio || 1)}px`;
              
              const context = canvas.getContext("2d");
              context.drawImage(img, 0, 0, canvas.width, canvas.height);
              canvas.dataset.rendered = "1";
            };
            img.src = cachedThumb;
          }
        } catch (e) {
          console.warn("恢复缓存缩略图失败:", e);
        }
      }
    });
    
    // 等待PDF加载完成
    pdfDoc = await loadingTask.promise;
    numPages.value = pdfDoc.numPages;

    // 预先获取每页尺寸
    pageWidths.value = [];
    pageHeights.value = [];
    
    // 先获取第一页尺寸，优先处理
    const firstPage = await pdfDoc.getPage(1);
    const firstViewport = firstPage.getViewport({ scale: scale.value });
    pageWidths.value[0] = firstViewport.width;
    pageHeights.value[0] = firstViewport.height;
    
    // 初始化只加载第一页
    visiblePages.value = new Set([1]);
    
    // 异步获取其他页面尺寸
    (async () => {
      for (let i = 2; i <= pdfDoc.numPages; i++) {
        try {
          const page = await pdfDoc.getPage(i);
          const viewport = page.getViewport({ scale: scale.value });
          pageWidths.value[i-1] = viewport.width;
          pageHeights.value[i-1] = viewport.height;
        } catch (e) {
          console.warn(`获取第${i}页尺寸失败:`, e);
        }
      }
    })();
    
    // PDF加载完成后，确保立即渲染第一个缩略图
    nextTick(async () => {
      thumbRefs.value = thumbRefs.value.filter(Boolean);
      pageRefs.value = pageRefs.value.filter(Boolean);
      
      // 先渲染第一个缩略图，确保其始终显示
      await ensureFirstThumbnailRendered();
      
      // 预加载前几页的缩略图
      setTimeout(() => {
        preloadInitialThumbnails();
      }, 100);
      
      thumbRefs.value.forEach((el, idx) => {
        observeThumb(el, idx + 1);
      });
      pageRefs.value.forEach((el, idx) => {
        observePage(el, idx + 1);
      });
    });
  } catch (error) {
    console.error("PDF加载失败:", error);
    
    // 根据错误类型设置不同的错误消息
    if (error.name === 'MissingPDFException') {
      setErrorState('文件未找到', 'PDF文件不存在或路径无效，请检查文件路径是否正确');
    } else if (error.name === 'InvalidPDFException') {
      setErrorState('无效的PDF文件', '文件格式不正确或已损坏，请检查文件是否为有效的PDF格式');
    } else if (error.name === 'UnexpectedResponseException') {
      setErrorState('网络错误', '无法加载PDF文件，请检查网络连接或文件服务器状态');
    } else if (error.name === 'PasswordException') {
      setErrorState('需要密码', '此PDF文件受密码保护，当前版本不支持密码验证');
    } else {
      setErrorState('加载失败', `PDF文件加载出错: ${error.message || '未知错误'}`);
    }
  }
};

// 确保第一个缩略图被渲染的函数
const ensureFirstThumbnailRendered = async () => {
  if (!pdfDoc) {
    // 如果PDF还没加载好，延迟重试
    return new Promise(resolve => {
      setTimeout(async () => {
        await ensureFirstThumbnailRendered();
        resolve();
      }, 100);
    });
  }
  
  // 确保缩略图canvas存在
  if (!thumbnailCanvases.value[0]) {
    // 等待DOM更新
    return new Promise(resolve => {
      nextTick(async () => {
        await ensureFirstThumbnailRendered();
        resolve();
      });
    });
  }
  
  // 如果第一个缩略图已经渲染过且没有空白问题，则不重复渲染
  const canvas = thumbnailCanvases.value[0];
  if (canvas.dataset.rendered && canvas.dataset.verified === "1") return;
  
  // 如果已经有渲染任务在进行，等待其完成
  if (renderingLocks.value[1]) {
    return new Promise(resolve => {
      const checkLock = () => {
        if (!renderingLocks.value[1]) {
          // 锁释放了，检查是否需要重新渲染
          if (!canvas.dataset.verified) {
            renderThumbnail(1, 0).then(resolve);
          } else {
            resolve();
          }
        } else {
          // 锁仍然存在，继续等待
          setTimeout(checkLock, 50);
        }
      };
      checkLock();
    });
  }
  
  // 直接调用渲染函数
  return renderThumbnail(1, 0);
};

// 预加载前几页的缩略图
const preloadInitialThumbnails = async () => {
  if (!pdfDoc) return;
  
  // 确定要预加载的页数，最多预加载前5页
  const pagesToPreload = Math.min(5, numPages.value);
  
  // 先确保第一页已经加载
  if (!renderingLocks.value[1]) {
    await ensureFirstThumbnailRendered();
  }
  
  // 然后按顺序加载剩下的页面
  for (let i = 2; i <= pagesToPreload; i++) {
    // 检查是否已经有渲染任务在进行
    if (!renderingLocks.value[i] && !renderedThumbs.value[i] && !pendingThumbs.value.has(i)) {
      pendingThumbs.value.add(i);
      await renderThumbnail(i, 0);
      renderedThumbs.value[i] = true;
      pendingThumbs.value.delete(i);
      
      // 短暂延迟，避免连续渲染导致的性能问题
      await new Promise(resolve => setTimeout(resolve, 10));
    }
  }
};

// 在script setup的开头添加渲染锁定机制
const renderingLocks = ref({}); // 用于跟踪每页的渲染状态

// 修改renderThumbnail函数，添加渲染锁定机制
async function renderThumbnail(page, retry) {
  // 如果该页面正在渲染中，跳过
  if (renderingLocks.value[page]) {
    console.log(`缩略图${page}正在渲染中，跳过重复渲染`);
    return;
  }
  
  const canvas = thumbnailCanvases.value[page - 1];
  if (!canvas) return;
  
  // 如果已经完全渲染和验证，则跳过
  if (canvas.dataset.rendered && canvas.dataset.verified === "1") return;
  
  // 如果PDF文档不可用，延迟重试
  if (!pdfDoc) {
    if (retry < 5) {
      setTimeout(() => renderThumbnail(page, (retry || 0) + 1), 100);
    }
    return;
  }
  
  // 设置渲染锁，防止同一页面同时被多次渲染
  renderingLocks.value[page] = true;
  
  try {
    // 确保获取页面对象成功
    const pdfPage = await pdfDoc.getPage(page);
    const scale = 0.18;
    const viewport = pdfPage.getViewport({ scale });
    const dpr = window.devicePixelRatio || 1;
    
    // 创建一个新的离屏canvas进行渲染，避免直接在显示的canvas上渲染
    const offscreenCanvas = document.createElement('canvas');
    offscreenCanvas.width = viewport.width * dpr;
    offscreenCanvas.height = viewport.height * dpr;
    
    // 获取绘图上下文
    const context = offscreenCanvas.getContext("2d");
    if (!context) {
      throw new Error("无法获取画布上下文");
    }
    
    // 先用背景色填充整个画布，防止透明或空白
    context.fillStyle = "#ffffff";
    context.fillRect(0, 0, offscreenCanvas.width, offscreenCanvas.height);
    
    // 设置变换
    context.setTransform(1, 0, 0, 1, 0, 0);
    context.setTransform(dpr, 0, 0, dpr, 0, 0);
    
    // 使用更高质量的渲染选项
    const renderOptions = {
      canvasContext: context,
      viewport,
      intent: 'display',
      enableWebGL: false,
      renderInteractiveForms: false
    };
    
    // 渲染页面到离屏画布
    await pdfPage.render(renderOptions).promise;
    
    // 验证渲染结果
    if (page === 1) {
      const imageData = context.getImageData(0, 0, offscreenCanvas.width, offscreenCanvas.height);
      const data = imageData.data;
      let nonEmptyPixels = 0;
      
      // 检查画布是否有非空像素
      for (let i = 0; i < data.length; i += 16) {
        if (data[i] !== 0 || data[i+1] !== 0 || data[i+2] !== 0 || data[i+3] !== 0) {
          nonEmptyPixels++;
        }
      }
      
      // 如果画布大部分是空的，可能渲染失败
      if (nonEmptyPixels < 100) {
        throw new Error("缩略图可能渲染不完整");
      }
    }
    
    // 渲染成功后，将离屏canvas的内容复制到显示canvas
    canvas.width = offscreenCanvas.width;
    canvas.height = offscreenCanvas.height;
    canvas.style.width = `${viewport.width}px`;
    canvas.style.height = `${viewport.height}px`;
    
    const displayContext = canvas.getContext("2d");
    displayContext.drawImage(offscreenCanvas, 0, 0);
    
    // 标记为已渲染
    canvas.dataset.rendered = "1";
    if (page === 1) {
      canvas.dataset.verified = "1";
      
      // 对第一页进行缓存
      try {
        const dataUrl = canvas.toDataURL('image/jpeg', 0.8);
        if (dataUrl && dataUrl.length > 1000) {
          localStorage.setItem(`pdf_thumb_cache_${props.src}_${page}`, dataUrl);
        }
      } catch (e) {
        console.warn("缓存缩略图失败:", e);
      }
    }
    
    // 如果是第一页，确保其他组件知道它已被渲染
    if (page === 1) {
      renderedThumbs.value[1] = true;
    }
  } catch (e) {
    console.error(`缩略图${page}渲染错误:`, e);
    
    // 尝试从缓存恢复
    if (page === 1) {
      try {
        const cachedThumb = localStorage.getItem(`pdf_thumb_cache_${props.src}_${page}`);
        if (cachedThumb) {
          const img = new Image();
          img.onload = () => {
            const context = canvas.getContext("2d");
            // 确保canvas尺寸正确
            canvas.width = img.width;
            canvas.height = img.height;
            canvas.style.width = `${img.width / (window.devicePixelRatio || 1)}px`;
            canvas.style.height = `${img.height / (window.devicePixelRatio || 1)}px`;
            
            // 清除画布并绘制图像
            context.clearRect(0, 0, canvas.width, canvas.height);
            context.drawImage(img, 0, 0);
            canvas.dataset.rendered = "1";
            canvas.dataset.verified = "1";
            
            // 释放渲染锁
            renderingLocks.value[page] = false;
          };
          img.src = cachedThumb;
          return; // 如果有缓存，不再重试
        }
      } catch (cacheErr) {
        console.warn("恢复缓存缩略图失败:", cacheErr);
      }
    }
    
    // 增加重试次数和间隔时间，特别是对第一页
    const maxRetries = page === 1 ? 8 : 3;
    const retryDelay = page === 1 ? 150 : 100;
    
    if (retry < maxRetries) {
      console.log(`重试渲染缩略图${page}，第${retry + 1}次`);
      setTimeout(() => {
        // 释放渲染锁后再重试
        renderingLocks.value[page] = false;
        renderThumbnail(page, (retry || 0) + 1);
      }, retryDelay);
    } else {
      // 达到最大重试次数，释放渲染锁
      renderingLocks.value[page] = false;
    }
  } finally {
    // 确保在正常情况下释放渲染锁
    if (!retry || retry >= 8) {
      renderingLocks.value[page] = false;
    }
  }
}

const onPageRendered = (page) => {
  // 当页面渲染完成时，标记为已渲染
  renderedPages.value.add(page);
  
  // 当第一页渲染完成时，立即确保第一个缩略图渲染
  if (page === 1) {
    // 使用Promise.resolve().then确保在微任务队列中执行，提高优先级
    Promise.resolve().then(async () => {
      // 检查是否已经有渲染任务在进行
      if (!renderingLocks.value[1]) {
        await renderThumbnail(1, 0);
      }
      // 如果第一页缩略图渲染失败，再次尝试
      if (thumbnailCanvases.value[0] && !thumbnailCanvases.value[0].dataset.verified) {
        setTimeout(async () => {
          // 再次检查是否已经被渲染
          if (thumbnailCanvases.value[0] && !thumbnailCanvases.value[0].dataset.verified && !renderingLocks.value[1]) {
            await ensureFirstThumbnailRendered();
          }
        }, 200);
      }
    });
  }
  
  pendingPages.value.delete(page);
  if (pendingThumbs.value.size === 0 && pendingPages.value.size === 0) {
    loading.value = false;
  }
  
  // 执行内存清理
  if (renderedPages.value.size > MAX_RENDERED_PAGES) {
    // 延迟执行，避免影响当前渲染
    setTimeout(() => {
      // 检查是否需要释放一些页面内存
      const currentPage = pageNumber.value;
      const pagesToKeep = new Set();
      
      // 保留当前页及其前后页
      for (let i = Math.max(1, currentPage - 2); i <= Math.min(numPages.value, currentPage + 2); i++) {
        pagesToKeep.add(i);
      }
      
      // 释放非关键页面
      renderedPages.value.forEach(p => {
        if (!pagesToKeep.has(p) && !visiblePages.value.has(p)) {
          const pageElement = pageRefs.value[p - 1];
          if (pageElement) {
            const canvas = pageElement.querySelector("canvas");
            if (canvas) {
              // 保存canvas引用以便可能的重用
              pageCanvasCache.value[p] = {
                width: canvas.width,
                height: canvas.height,
                style: canvas.style.cssText
              };
              // 清除canvas内容释放内存
              canvas.width = 0;
              canvas.height = 0;
              canvas.remove();
            }
          }
          renderedPages.value.delete(p);
        }
      });
    }, 100);
  }
};

const goToPage = (page) => {
  pageNumber.value = page;
  nextTick(() => {
    const el = pageRefs.value[page - 1];
    if (el && contentRef.value) {
      contentRef.value.scrollTop = el.offsetTop;
    }
  });
};

const PRELOAD_WINDOW = 5;

// 在script setup部分添加内存管理相关变量
const MAX_RENDERED_PAGES = 10; // 最大同时渲染的页面数
const MAX_RENDERED_THUMBS = 20; // 最大同时渲染的缩略图数
const pageCanvasCache = ref({}); // 缓存页面canvas引用
const renderedPages = ref(new Set()); // 跟踪已渲染的页面

// 修改visiblePages的watch函数，添加内存管理
watch(visiblePages, (newSet, oldSet) => {
  // 清理不再可见的页面
  oldSet.forEach((page) => {
    if (!newSet.has(page)) {
      // 移除页面DOM
      const pageElement = pageRefs.value[page - 1];
      if (pageElement) {
        const canvas = pageElement.querySelector("canvas");
        if (canvas) {
          // 保存canvas引用以便可能的重用
          pageCanvasCache.value[page] = {
            width: canvas.width,
            height: canvas.height,
            style: canvas.style.cssText
          };
          // 清除canvas内容释放内存
          canvas.width = 0;
          canvas.height = 0;
          canvas.remove();
        }
      }
      // 从已渲染集合中移除
      renderedPages.value.delete(page);
    }
  });
  
  // 检查是否超过最大渲染页数
  if (newSet.size > MAX_RENDERED_PAGES) {
    // 找出当前页面和其前后的重要页面
    const currentPage = pageNumber.value;
    const importantPages = new Set();
    
    // 当前页及其前后各2页是重要页面
    for (let i = Math.max(1, currentPage - 2); i <= Math.min(numPages.value, currentPage + 2); i++) {
      importantPages.add(i);
    }
    
    // 找出可以释放的页面（非重要且已渲染）
    const pagesToRelease = [];
    newSet.forEach(page => {
      if (!importantPages.has(page) && renderedPages.value.has(page)) {
        pagesToRelease.push(page);
      }
    });
    
    // 按照与当前页距离排序，释放最远的页面
    pagesToRelease.sort((a, b) => 
      Math.abs(b - currentPage) - Math.abs(a - currentPage)
    );
    
    // 释放内存直到低于最大限制
    while (pagesToRelease.length > 0 && newSet.size - pagesToRelease.length >= MAX_RENDERED_PAGES / 2) {
      const pageToRelease = pagesToRelease.shift();
      const pageElement = pageRefs.value[pageToRelease - 1];
      
      if (pageElement) {
        const canvas = pageElement.querySelector("canvas");
        if (canvas) {
          // 保存canvas引用以便可能的重用
          pageCanvasCache.value[pageToRelease] = {
            width: canvas.width,
            height: canvas.height,
            style: canvas.style.cssText
          };
          // 清除canvas内容释放内存
          canvas.width = 0;
          canvas.height = 0;
          canvas.remove();
        }
      }
      
      // 从集合中移除但保留在visiblePages中
      renderedPages.value.delete(pageToRelease);
      
      // 从visiblePages中移除
      visiblePages.value.delete(pageToRelease);
    }
  }
}, { deep: true });

// 添加缩略图内存管理函数
const cleanupThumbnails = () => {
  // 如果缩略图数量超过限制，清理一些不在视口中的缩略图
  const renderedThumbsCount = Object.keys(renderedThumbs.value).length;
  
  if (renderedThumbsCount > MAX_RENDERED_THUMBS) {
    // 获取当前页面和其前后的重要缩略图
    const currentPage = pageNumber.value;
    const importantThumbs = new Set();
    
    // 当前页及其前后各5页是重要缩略图
    for (let i = Math.max(1, currentPage - 5); i <= Math.min(numPages.value, currentPage + 5); i++) {
      importantThumbs.add(i);
    }
    
    // 找出可以释放的缩略图（非重要且已渲染）
    const thumbsToRelease = [];
    Object.keys(renderedThumbs.value).forEach(page => {
      page = parseInt(page);
      if (!importantThumbs.has(page) && page !== 1) { // 保留第一页缩略图
        thumbsToRelease.push(page);
      }
    });
    
    // 按照与当前页距离排序，释放最远的缩略图
    thumbsToRelease.sort((a, b) => 
      Math.abs(b - currentPage) - Math.abs(a - currentPage)
    );
    
    // 释放内存直到低于最大限制
    const thumbsToKeep = MAX_RENDERED_THUMBS * 0.7; // 保留70%作为缓冲
    while (thumbsToRelease.length > 0 && renderedThumbsCount - thumbsToRelease.length > thumbsToKeep) {
      const thumbToRelease = thumbsToRelease.shift();
      const canvas = thumbnailCanvases.value[thumbToRelease - 1];
      
      if (canvas) {
        // 清除canvas内容释放内存
        canvas.width = 0;
        canvas.height = 0;
        canvas.removeAttribute('data-rendered');
        canvas.removeAttribute('data-verified');
      }
      
      // 从渲染集合中移除
      delete renderedThumbs.value[thumbToRelease];
    }
  }
};

// 修改handleScroll函数，添加内存管理
const handleScroll = () => {
  if (!contentRef.value || !pageRefs.value.length) return;
  const scrollTop = contentRef.value.scrollTop;
  let minDiff = Infinity;
  let currentPage = 1;
  pageRefs.value.forEach((el, idx) => {
    if (!el) return;
    const diff = Math.abs(el.offsetTop - scrollTop);
    if (diff < minDiff) {
      minDiff = diff;
      currentPage = idx + 1;
    }
  });

  // 修正：如果滚动条到底，currentPage = 最后一页
  const isAtBottom =
    Math.abs(
      contentRef.value.scrollHeight -
        contentRef.value.scrollTop -
        contentRef.value.clientHeight
    ) < 2; // 允许2px误差
  if (isAtBottom) {
    currentPage = numPages.value;
  }

  if (pageNumber.value !== currentPage) {
    pageNumber.value = currentPage;
    
    // 页面变化时执行内存清理
    cleanupThumbnails();
  }
  
  // 维护 visiblePages，扩大窗口
  const newVisible = new Set();
  for (
    let p = Math.max(1, currentPage - PAGE_WINDOW);
    p <= Math.min(numPages.value, currentPage + PAGE_WINDOW);
    p++
  ) {
    newVisible.add(p);
  }
  
  // 添加预加载页面
  for (
    let p = Math.max(1, currentPage - PAGE_WINDOW - PRELOAD_WINDOW);
    p < Math.max(1, currentPage - PAGE_WINDOW);
    p++
  ) {
    // 只添加少量预加载页面，避免内存过度使用
    if (newVisible.size < MAX_RENDERED_PAGES) {
      newVisible.add(p);
    }
  }
  
  for (
    let p = Math.min(numPages.value, currentPage + PAGE_WINDOW) + 1;
    p <= Math.min(numPages.value, currentPage + PAGE_WINDOW + PRELOAD_WINDOW);
    p++
  ) {
    // 只添加少量预加载页面，避免内存过度使用
    if (newVisible.size < MAX_RENDERED_PAGES) {
      newVisible.add(p);
    }
  }
  
  // 更新可见页面集合
  visiblePages.value.forEach((p) => {
    if (!newVisible.has(p)) visiblePages.value.delete(p);
  });
  newVisible.forEach((p) => {
    visiblePages.value.add(p);
    // 标记为已渲染
    if (p === currentPage) {
      renderedPages.value.add(p);
    }
  });
};

const toggleFullScreen = () => {
  const el = viewerRoot.value;
  if (!el) return;
  if (!document.fullscreenElement) {
    el.requestFullscreen();
  } else {
    document.exitFullscreen();
  }
};
const prevPage = () => {
  if (pageNumber.value > 1) pageNumber.value--;
};
const nextPage = () => {
  if (pageNumber.value < numPages.value) pageNumber.value++;
};
const zoomIn = () => {
  scale.value = Math.min(scale.value + 0.1, 3);
  updatePageDimensions();
};
const zoomOut = () => {
  scale.value = Math.max(scale.value - 0.1, 0.2);
  updatePageDimensions();
};

// 添加更新页面尺寸的方法
const updatePageDimensions = async () => {
  if (!pdfDoc) return;
  
  // 更新页面尺寸
  for (let i = 1; i <= pdfDoc.numPages; i++) {
    const page = await pdfDoc.getPage(i);
    const viewport = page.getViewport({ scale: scale.value });
    pageWidths.value[i - 1] = viewport.width;
    pageHeights.value[i - 1] = viewport.height;
  }
};

// 监听缩放变化
watch(scale, async (newScale, oldScale) => {
  if (Math.abs(newScale - oldScale) > 0.01) {
    await updatePageDimensions();
  }
});
const downloadPdf = () => {
  const link = document.createElement("a");
  link.href = props.src;
  link.download = filename.value;
  link.click();
};
const printPdf = () => {
  window.open(props.src, "_blank");
};

const toggleThumbnails = () => {
  showThumbnails.value = !showThumbnails.value;
};

watch(() => props.src, loadPdf, { immediate: true });
watch(pageNumber, (newPage) => {
  nextTick(() => {
    const el = thumbRefs.value[newPage - 1];
    if (el && thumbnailsContainer.value) {
      el.scrollIntoView({ behavior: "smooth", block: "center" });
    }
  });
});

// 在 visiblePages 变化时，移除不在窗口内的页面
watch(visiblePages, (newSet, oldSet) => {
  oldSet.forEach((page) => {
    if (!newSet.has(page)) {
      // 可以在这里手动销毁 PdfViewer 组件或清空其 canvas
      pageRefs.value[page - 1]?.querySelector("canvas")?.remove();
    }
  });
});

let scrollTimeout = null;
function throttledHandleScroll() {
  if (scrollTimeout) return;
  scrollTimeout = setTimeout(() => {
    handleScroll();
    scrollTimeout = null;
  }, 100); // 100ms 可根据实际体验调整
}

// 定义事件处理函数，以便于添加和移除
const handleResize = () => {
  // 窗口大小变化时，检查第一页缩略图
  if (thumbnailCanvases.value[0] && !thumbnailCanvases.value[0].dataset.verified && !renderingLocks.value[1]) {
    renderThumbnail(1, 0);
  }
};

const handleVisibilityChange = () => {
  if (document.visibilityState === 'visible') {
    // 页面变为可见时，检查第一页缩略图
    if (thumbnailCanvases.value[0] && !thumbnailCanvases.value[0].dataset.verified && !renderingLocks.value[1]) {
      renderThumbnail(1, 0);
    }
  }
};

// 添加定期内存清理
let memoryCleanupInterval;
onMounted(() => {
  if (contentRef.value) {
    contentRef.value.addEventListener("scroll", throttledHandleScroll);
  }
  
  // 组件挂载后，立即开始预加载过程
  setTimeout(async () => {
    // 检查第一个缩略图是否已渲染
    if (pdfDoc && thumbnailCanvases.value[0]) {
      if (!thumbnailCanvases.value[0].dataset.rendered && !renderingLocks.value[1]) {
        await ensureFirstThumbnailRendered();
      } else if (!thumbnailCanvases.value[0].dataset.verified && !renderingLocks.value[1]) {
        // 如果已渲染但未验证，可能是从缓存恢复的，进行验证
        try {
          const context = thumbnailCanvases.value[0].getContext("2d");
          const imageData = context.getImageData(
            0, 0, 
            thumbnailCanvases.value[0].width, 
            thumbnailCanvases.value[0].height
          );
          const data = imageData.data;
          let nonEmptyPixels = 0;
          
          // 检查画布是否有非空像素
          for (let i = 0; i < data.length; i += 16) {
            if (data[i] !== 0 || data[i+1] !== 0 || data[i+2] !== 0 || data[i+3] !== 0) {
              nonEmptyPixels++;
            }
          }
          
          // 如果画布大部分是空的，重新渲染
          if (nonEmptyPixels < 100) {
            await renderThumbnail(1, 0);
          } else {
            thumbnailCanvases.value[0].dataset.verified = "1";
          }
        } catch (e) {
          // 验证失败，重新渲染
          await renderThumbnail(1, 0);
        }
      }
    }
    
    // 预加载前几页缩略图
    preloadInitialThumbnails();
  }, 300);
  
  // 添加全局事件监听
  window.addEventListener('resize', handleResize);
  document.addEventListener('visibilitychange', handleVisibilityChange);
  
  // 设置定期内存清理
  memoryCleanupInterval = setInterval(() => {
    // 执行内存清理
    cleanupThumbnails();
    
    // 强制执行垃圾回收（仅在开发环境，生产环境无效但无害）
    if (window.gc) {
      try {
        window.gc();
      } catch (e) {}
    }
  }, 30000); // 每30秒执行一次
});

onBeforeUnmount(() => {
  if (contentRef.value) {
    contentRef.value.removeEventListener("scroll", throttledHandleScroll);
  }
  
  // 清理添加的全局事件监听器
  window.removeEventListener('resize', handleResize);
  document.removeEventListener('visibilitychange', handleVisibilityChange);
  
  // 清除定期内存清理
  if (memoryCleanupInterval) {
    clearInterval(memoryCleanupInterval);
  }
  
  // 清理所有缓存和引用
  pageCanvasCache.value = {};
  renderedPages.value.clear();
  renderedThumbs.value = {};
  pendingThumbs.value.clear();
  pendingPages.value.clear();
  
  // 清理所有canvas
  thumbnailCanvases.value.forEach(canvas => {
    if (canvas) {
      canvas.width = 0;
      canvas.height = 0;
    }
  });
  
  if (pdfDoc && pdfDoc.destroy) {
    pdfDoc.destroy();
    pdfDoc = null;
  }
});


const observeThumb = (el, page) => {
  if (!el || observedThumbs.value[page]) return;
  observedThumbs.value[page] = true;
  const observer = new IntersectionObserver(
    (entries) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          [page - 10, page, page + 10].forEach((p) => {
            if (
              p > 0 &&
              p <= numPages.value &&
              !renderedThumbs.value[p] &&
              !pendingThumbs.value.has(p)
            ) {
              pendingThumbs.value.add(p);
              loading.value = true;
              requestAnimationFrame(() => {
                renderThumbnail(p, 0).then(() => {
                  renderedThumbs.value[p] = true;
                  pendingThumbs.value.delete(p);
                  if (pendingThumbs.value.size === 0 && pendingPages.value.size === 0) {
                    loading.value = false;
                  }
                });
              });
            }
          });
        }
      });
    },
    { root: thumbnailsContainer.value, threshold: 0.1 }
  );
  observer.observe(el);
};

// 主内容懒加载
function observePage(el, page) {
  if (!el) return;
  const observer = new IntersectionObserver(
    (entries) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          visiblePages.value.add(page);
        }
      });
    },
    { root: contentRef.value, threshold: 0.1 }
  );
  observer.observe(el);
}
</script>

<style scoped>
/* 错误提示样式 */
.pdfjs-error-container {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 40px 20px;
  text-align: center;
}

.pdfjs-error-content {
  max-width: 400px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 20px;
}

.error-icon {
  opacity: 0.6;
  color: #ff6b6b;
}

.pdfjs-error-content h3 {
  font-size: 24px;
  font-weight: 600;
  margin: 0;
}

.pdfjs-error-content p {
  font-size: 16px;
  line-height: 1.6;
  margin: 0;
  opacity: 0.8;
}

.retry-btn {
  padding: 12px 24px;
  border: none;
  border-radius: 6px;
  font-size: 16px;
  font-weight: 500;
  cursor: pointer;
  transition: all 0.2s ease;
  box-shadow: 0 2px 8px rgba(0,0,0,0.1);
}

.retry-btn:hover {
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(0,0,0,0.15);
}

.retry-btn:active {
  transform: translateY(0);
}

.pdfjs-page-placeholder {
  width: 100%;
  background: #222;
  margin: 10px 0;
  border-radius: 4px;
  transition: all 0.3s ease;
}

.pdfjs-viewer-root {
  position: relative;
  height: 100vh;
  background: #222;
  display: flex;
  flex-direction: column;
}

.pdf-indeterminate-bar {
  position: relative; /* 让进度条在文档流中，紧跟工具栏 */
  width: 100%;
  height: 3px;
  background: transparent;
  z-index: 20;
  overflow: hidden;
}

.pdf-indeterminate-inner {
  width: 30%;
  height: 100%;
  background: #2196f3;
  position: absolute;
  left: -30%;
  animation: indeterminate-bar 1.2s infinite cubic-bezier(0.4, 0, 0.2, 1);
  border-radius: 2px;
}

@keyframes indeterminate-bar {
  0% {
    left: -30%;
    width: 30%;
  }
  50% {
    left: 35%;
    width: 30%;
  }
  100% {
    left: 100%;
    width: 30%;
  }
}
.pdfjs-viewer-root {
  height: 100vh;
  background: #222;
  display: flex;
  flex-direction: column;
}
.pdfjs-toolbar {
  height: 48px;
  background: #333;
  color: #fff;
  display: flex;
  align-items: center;
  padding: 0 24px;
  box-shadow: 0 2px 8px #0002;
  z-index: 10;
  justify-content: space-between;
}
.pdfjs-toolbar-left,
.pdfjs-toolbar-center,
.pdfjs-toolbar-right {
  display: flex;
  align-items: center;
  gap: 10px;
}
.pdfjs-toolbar-left {
  min-width: 0;
  flex: 1 1 0;
}
.pdfjs-toolbar-center {
  justify-content: center;
  flex: 2 1 0;
}
.pdfjs-toolbar-right {
  justify-content: flex-end;
  flex: 1 1 0;
}
.pdfjs-filename {
  font-weight: bold;
  font-size: 18px;
  margin-right: 32px;
}
.pdfjs-toolbar button {
  background: none;
  border: none;
  font-size: 18px;
  padding: 4px 8px;
  border-radius: 4px;
  cursor: pointer;
  transition: background 0.2s;
}
.pdfjs-toolbar button:disabled {
  color: #888;
  cursor: not-allowed;
}
.pdfjs-toolbar button:hover:not(:disabled) {
  background: var(--button-hover-color, #444);
}
.pdfjs-main {
  flex: 1;
  display: flex;
  min-height: 0;
  overflow: hidden;
}
.pdfjs-thumbnails {
  width: 120px;
  background: #232323;
  overflow-y: auto;
  padding: 12px 0;
  border-right: 1px solid #333;
}
.pdfjs-thumbnail {
  margin: 0 auto 12px auto;
  cursor: pointer;
  border: 2px solid transparent;
  border-radius: 4px;
  /* background: #181818; */
  padding: 4px;
  width: 90px;
  transition: border-color 0.2s, background 0.2s;
  text-align: center;
}
.pdfjs-thumbnail.active {
  border-color: var(--primary-color, #42b983);
  background: #2a2a2a;
}
.pdfjs-thumbnail canvas {
  max-width: 100%;
  height: auto;
  display: block;
  margin: 0 auto 4px auto;
  background: #fff;
  border-radius: 2px;
}
.pdfjs-thumbnail span {
  color: #bbb;
  font-size: 13px;
}
.pdfjs-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  align-items: center;
  background: #222;
  overflow: auto;
  min-height: 0;
  /* height: 100%;  // 删除这一行 */
  box-sizing: border-box;
}

.pdfjs-page {
  display: flex;
  justify-content: center;
  align-items: center;
  margin: 10px 0;
  width: 100%;
}

.pdfjs-page-placeholder {
  width: 100%;
  height: 1000px; /* 默认高度，实际会根据页面比例调整 */
  background: #222;
  margin: 10px 0;
}

.pdfjs-viewer-root:fullscreen {
  background: #111;
  width: 100vw;
  height: 100vh;
  /* 其他你想要的全屏样式 */
}
</style>
